package com.example.gobang.api;

import com.example.gobang.game.*;
import com.example.gobang.model.User;
import com.example.gobang.model.UserMapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;

@Component
public class GameApi extends TextWebSocketHandler {
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private onlineUserManager onlineUserManager1;
    @Autowired
private Matcher matcher;
    @Autowired
    private RoomManger roomManger;
    @Autowired
    private UserMapper userMapper;

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        GameReadyReponse gameReadyReponse = new GameReadyReponse();
        User user = (User) session.getAttributes().get("user");
        if (user == null) {
            gameReadyReponse.setOk(false);
            gameReadyReponse.setReason("用户尚未登录");
        //gameReadyReponse.sendMessage(String.valueOf(new TextMessage(objectMapper.writeValueAsString(gameReadyReponse))));
          session.sendMessage(new TextMessage(objectMapper.writeValueAsString(gameReadyReponse)));
            return;
        }
        // 使用已注入的 roomManger 实例，而不是创建新实例
        Room room = roomManger.getRoomBYUserId(user.getUserId());
        if (room == null) {
            gameReadyReponse.setOk(false);
            gameReadyReponse.setReason("用户尚未登录");
          //  gameReadyReponse.setMessage(String.valueOf(new TextMessage(objectMapper.writeValueAsString(gameReadyReponse))));
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(gameReadyReponse)));
            return;
        }
        if (onlineUserManager1.getFromGameHall(user.getUserId()) != null || onlineUserManager1.getFromGameRoom(user.getUserId()) != null) {
            gameReadyReponse.setOk(true);

            gameReadyReponse.setReason("禁止多开");
            gameReadyReponse.setMessage("repeatConnection");
          //  gameReadyReponse.setMessage(String.valueOf(new TextMessage(objectMapper.writeValueAsString(gameReadyReponse))));
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(gameReadyReponse)));
            return;
        }

        onlineUserManager1.enterGameRRoom(user.getUserId(), session);


        synchronized (room) {
            if (room.getUser1() == null) {
                room.setUser1(user);
                room. setUser1(user);
                System.out.println("玩家 " + user.getUsername() + " 已经准备就绪！作为玩家 1");
                return;
            }
            if (room.getUser2() == null) {

                room.setUser2(user);
                System.out.println("玩家 " + user.getUsername() + " 已经准备就绪！作为玩家 2");

                // 设置先手玩家（白棋）
                room.setWhiteUser(room.getUser1().getUserId());
                System.out.println("设置玩家 " + room.getUser1().getUsername() + " 为先手（白棋）");

                noticeGameReady(room, room.getUser1(), room.getUser2());
                // 通知玩家 2

                noticeGameReady(room, room.getUser2(), room.getUser1());
                return;
            }

        }
        gameReadyReponse.setOk(false);
        gameReadyReponse.setReason("当前房间已满，您不能加入房间");
        session.sendMessage(new TextMessage(objectMapper.writeValueAsString(gameReadyReponse)));

    }

    private void noticeGameReady(Room room, User thisUser, User thatUser) throws IOException {
        GameReadyReponse resp = new GameReadyReponse();
        resp.setMessage("gameReady");
        resp.setOk(true);
        resp.setReason("");
        resp.setRoomId(room.getRoomId());
        resp.setThisUserId(thisUser.getUserId());

        resp.setThatUserId(thatUser.getUserId());
        resp.setWhiteUser(room.getWhiteUser());
        // 把当前的响应数据传回给玩家。

        WebSocketSession webSocketSession = onlineUserManager1.getFromGameRoom(thisUser.getUserId());
        webSocketSession.sendMessage(new TextMessage(objectMapper.writeValueAsString(resp)));
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
          User user = (User) session.getAttributes().get("user");
          if(user==null){
              System.out.println("尚未登录");
              return;
          }
          Room room = roomManger.getRoomBYUserId(user.getUserId());
          if(room == null){
              System.out.println("错误：找不到用户" + user.getUsername() + "所在的房间");
              return;
          }
          room.putChess(message.getPayload());
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {

        User user = (User) session.getAttributes().get("user");
        if (user == null) {
            // 此处就简单处理，在断开连接的时候就不给客户端返回响应了。

            return;
        }
        WebSocketSession exitSession = onlineUserManager1.getFromGameRoom(user.getUserId());
        if (session == exitSession) {
            // 加上这个判定，目的是为了避免在多开的情况下，第二个用户退出连接动作，导致第一个用户的会话被删除。

            onlineUserManager1.exitGameRoom(user.getUserId());
        }
        System.out.println("当前用户 " + user.getUsername() + " 游戏房间连接异常！");

        // 通知对手获胜了

        noticeThatUserWin(user);

    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {

        User user = (User) session.getAttributes().get("user");
        if (user == null) {
            // 此处就简单处理，在断开连接的时候就不给客户端返回响应了。

            return;
        }
        WebSocketSession exitSession = onlineUserManager1.getFromGameRoom(user.getUserId());
        if (session == exitSession) {
            // 加上这个判定，目的是为了避免在多开的情况下，第二个用户退出连接动作，导致第一个用户的会话被删除。

            onlineUserManager1.exitGameRoom(user.getUserId());
        }
        System.out.println("当前用户 " + user.getUsername() + " 离开游戏房间！");

        // 通知对手获胜了

        noticeThatUserWin(user);

    }

    private void noticeThatUserWin(User user) throws IOException {
        // 1. 根据当前玩家，找到玩家所在的房间

        Room room =roomManger.getRoomBYUserId(user.getUserId());
        if (room == null) {
            // 这个情况意味着房间已经被释放了，也就没有 "对手" 了

            System.out.println("当前房间已经释放，无需通知对手！");
            return;
        }

        // 2. 根据房间找到对手

        User thatUser = (user == room.getUser1()) ? room.getUser2() : room.getUser1();
        // 3. 找到对手的在线状态

        WebSocketSession webSocketSession = onlineUserManager1.getFromGameRoom(thatUser.getUserId());
        if (webSocketSession == null) {
            // 这就意味着对手也掉线了！

            System.out.println("对手也已经掉线了，无需通知！");
            return;
        }
        // 4. 构造一个响应，来通知对手，你是获胜方

        GameReponse resp = new GameReponse();
        resp.setMessage("putChess");
        resp.setUserId(thatUser.getUserId());
        resp.setWinner(thatUser.getUserId());
        webSocketSession.sendMessage(new TextMessage(objectMapper.writeValueAsString(resp)));

        // 5. 更新玩家的分数信息

        int winUserId = thatUser.getUserId();
        int loseUserId = user.getUserId();
        userMapper.useWin(winUserId);
        userMapper.userLose(loseUserId);

        // 6. 释放房间对象

        roomManger.remove(room.getRoomId(), room.getUser1().getUserId(), room.getUser2().getUserId());
    }

}
